package com.javabi.htmlbuilder.html.element.form;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.javabi.htmlbuilder.html.HTMLBuilder;
import com.javabi.htmlbuilder.html.HTMLElement;
import com.javabi.htmlbuilder.html.HTMLElementName;

/**
 * A Form Select Drop-Down Box.
 */
public class Select extends HTMLElement<Select> {

	/** The name. */
	private String name = null;
	/** The option list. */
	private final List<Option> optionList = new ArrayList<Option>();

	/**
	 * Creates a new Select.
	 */
	public Select() {
	}

	/**
	 * Creates a new Select.
	 * @param name the name.
	 * @param values the values.
	 */
	public Select(String name, Object[] values) {
		if (values.length == 0) {
			throw new IllegalArgumentException("values is empty");
		}
		setName(name);
		for (Object value : values) {
			option(value).text(value);
		}
	}

	/**
	 * Creates a new Select.
	 * @param name the name.
	 * @param values the values.
	 */
	public Select(String name, Collection<?> values) {
		if (values.isEmpty()) {
			throw new IllegalArgumentException("values is empty");
		}
		setName(name);
		for (Object value : values) {
			option(value).text(value);
		}
	}

	/**
	 * Creates a new Select.
	 * @param name the name.
	 * @param values the values.
	 * @param selectedValue the selected value.
	 */
	public Select(String name, Object[] values, Object selectedValue) {
		if (values.length == 0) {
			throw new IllegalArgumentException("values is empty");
		}
		if (selectedValue == null) {
			throw new NullPointerException();
		}
		setName(name);
		for (Object value : values) {
			Option option = option(value);
			if (value.equals(selectedValue)) {
				option.setSelected(true);
			}
			option.text(value);
		}
	}

	/**
	 * Creates a new Select.
	 * @param name the name.
	 * @param values the enumerated values.
	 */
	public <E extends Enum<E>> Select(String name, Class<E> values) {
		this(name, values.getEnumConstants());
	}

	/**
	 * Creates a new Select.
	 * @param name the name.
	 * @param selectedValue the selected value (from an enumeration).
	 */
	public <E extends Enum<E>> Select(String name, E selectedValue) {
		this(name, selectedValue.getClass().getEnumConstants(), selectedValue);
	}

	/**
	 * Creates a new Select.
	 * @param name the name.
	 * @param values the enumerated values.
	 * @param selectedValue the selected value.
	 */
	public <E extends Enum<E>> Select(String name, Class<E> values, E selectedValue) {
		this(name, values.getEnumConstants(), selectedValue);
	}

	/**
	 * Returns the name
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * Sets the name
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * Returns the element name.
	 * @return the element name.
	 */
	public HTMLElementName getElementName() {
		return HTMLElementName.SELECT;
	}

	/**
	 * Returns a new option for this select.
	 * @return the option.
	 */
	public Option option() {
		Option option = new Option();
		optionList.add(option);
		return option;
	}

	/**
	 * Returns a new option for this select.
	 * @param value the value.
	 * @return the option.
	 */
	public Option option(Object value) {
		Option option = option();
		option.setValue(value);
		return option;
	}

	/**
	 * Append this to the given html builder.
	 * @param html the html builder.
	 * @return the html builder.
	 */
	public HTMLBuilder appendTo(HTMLBuilder html) {
		html.open(this, true);
		appendInlineStyleAttributesTo(html);
		if (name != null) {
			html.attribute("name", name);
		}
		for (Option option : optionList) {
			option.appendTo(html);
		}
		html.close(this);
		return html;
	}

	/**
	 * Returns true to format this element.
	 * @return true to format this element.
	 */
	public boolean format() {
		return true;
	}

}
